﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using YArchitech.ProgressBar;
using YArchitech.Revit;
using HyMaterialStatistic;
using HYView;
using Transfer.Utils;

namespace PlumbingMaterialStatistic
{
	internal class PlumbingMaterialStatisticData
	{
		public PlumbingMaterialStatisticData(Autodesk.Revit.DB.Document doc)
		{
			this.m_doc = doc;
			this.m_lstSortLevel = FloorSelectManager.GetSortLevels(doc, double.MinValue, double.MaxValue);
		}

		public void GetStatisticElement(bool bLink, List<ViewPlan> lstViewPlan, List<FilterInfo> lstFilterInfo, List<string> lstSystem, List<string> lstPipeMaterial)
		{
			this.m_bLink = bLink;
			this.m_lstViewPlan = lstViewPlan;
			this.m_lstFilterInfo = lstFilterInfo;
			if (bLink)
			{
				this.m_lstLevelValue = this.GetLevelValue();
				this.m_view3D = this.GetView3D();
			}
			this.m_lstSystem = lstSystem;
			this.m_lstPipeMaterial = lstPipeMaterial;
			this.m_lstDicElement.Clear();
			this.ElementInDoc();
			if (this.m_bLink)
			{
				this.ElementInLinkDoc();
			}
		}

		public void GetStatisticElement(ViewPlan view, List<FilterInfo> lstFilterInfo, List<string> lstSystem, List<Element> lstElemSelArea, List<string> lstPipeMaterial)
		{
			this.m_view = view;
			this.m_lstFilterInfo = lstFilterInfo;
			this.m_lstSystem = lstSystem;
			this.m_lstElemInSelArea = lstElemSelArea;
			this.m_lstPipeMaterial = lstPipeMaterial;
			this.m_lstDicElement.Clear();
			this.ElementInSelAreaDoc();
		}

		private void ElementInDoc()
		{
			ProgressBarForm progressBarForm = new ProgressBarForm(this.m_lstFilterInfo.Count * this.m_lstViewPlan.Count, "正在统计主文档中的数据", ProgressBarStyle.Blocks, true, false, false);
			progressBarForm.Show(WindowHelper.HWndRevit);
			for (int i = 0; i < this.m_lstFilterInfo.Count; i++)
			{
				Dictionary<ElementId, ElemParm> item = new Dictionary<ElementId, ElemParm>();
				foreach (ViewPlan viewPlan in this.m_lstViewPlan)
				{
					progressBarForm.RefreshProgressBar();
					if (progressBarForm.m_stopTag)
					{
						return;
					}
					ElementId elementId = viewPlan.GetUnderLayParameter().AsElementId();
					Transaction transaction = new Transaction(this.m_doc, "ChangeBaseLine");
					transaction.Start();
					viewPlan.GetUnderLayParameter().Set(ElementId.InvalidElementId);
					transaction.Commit();
					try
					{
						FilterInfo filterInfo = this.m_lstFilterInfo[i];
						FilteredElementCollector collector = new FilteredElementCollector(this.m_doc, viewPlan.Id);
						BuiltInCategory biCategory = (BuiltInCategory)Enum.Parse(typeof(BuiltInCategory), filterInfo.Category);
						if (filterInfo.Class == "FamilyInstance")
						{
							this.GetNonSystemFamilyInfo(filterInfo, collector, biCategory, ref item);
						}
						else
						{
							this.GetSystemFamilyInfo(filterInfo, collector, biCategory, viewPlan.GenLevel.Elevation, ref item);
						}
					}
					catch
					{
						continue;
					}
					transaction.Start();
					viewPlan.GetUnderLayParameter().Set(elementId);
					transaction.Commit();
				}
				this.m_lstDicElement.Add(item);
			}
		}

		private void ElementInSelAreaDoc()
		{
			ProgressBarForm progressBarForm = new ProgressBarForm(this.m_lstFilterInfo.Count, "正在统计绘制区域中的数据", ProgressBarStyle.Blocks, true, false, false);
			progressBarForm.Show(WindowHelper.HWndRevit);
			for (int i = 0; i < this.m_lstFilterInfo.Count; i++)
			{
				progressBarForm.RefreshProgressBar();
				if (progressBarForm.m_stopTag)
				{
					return;
				}
				Dictionary<ElementId, ElemParm> item = new Dictionary<ElementId, ElemParm>();
				FilterInfo filterInfo = this.m_lstFilterInfo[i];
				BuiltInCategory biCategory = (BuiltInCategory)Enum.Parse(typeof(BuiltInCategory), filterInfo.Category);
				if (filterInfo.Class == "FamilyInstance")
				{
					this.GetNonSystemFamilyInfo(filterInfo, biCategory, ref item);
				}
				else
				{
					this.GetSystemFamilyInfo(filterInfo, biCategory, ref item);
				}
				this.m_lstDicElement.Add(item);
			}
		}

		private void GetNonSystemFamilyInfo(FilterInfo filterInfo, FilteredElementCollector collector, BuiltInCategory biCategory, ref Dictionary<ElementId, ElemParm> dicSubItems)
		{
			foreach (Element element in collector.OfClass(typeof(FamilyInstance)).OfCategory(biCategory).ToElements())
			{
				if (this.m_bLink || !dicSubItems.ContainsKey(element.Id))
				{
					if (filterInfo.Category != "OST_MechanicalEquipment")
					{
						string item = element.GetParameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).AsValueString();
						if (!this.m_lstSystem.Contains(item))
						{
							continue;
						}
					}
					FamilyInstance familyInstance = element as FamilyInstance;
					string name = familyInstance.Symbol.Family.Name;
					string name2 = familyInstance.Symbol.Family.Name;
					string strDetailInfo = "";
					this.GetParmInfo(element, filterInfo.ValueType, filterInfo.ConnSymbol, filterInfo.BuiltInParm, ref strDetailInfo);
					ElemParm elemParm = new ElemParm(name, name2, strDetailInfo, filterInfo.Unit, 1.0, "", filterInfo.DetailFilter);
					this.AddInDictionary(element.Id, elemParm, ref dicSubItems);
				}
			}
		}

		private void GetNonSystemFamilyInfo(FilterInfo filterInfo, BuiltInCategory biCategory, ref Dictionary<ElementId, ElemParm> dicSubItems)
		{
			foreach (Element element in this.m_lstElemInSelArea)
			{
				if (dicSubItems.ContainsKey(element.Id))
				{
					dicSubItems[element.Id].Amount += 1.0;
				}
                else if (element is FamilyInstance && element.Category.Id.IntegerValue == (int)biCategory)
				{
					if (filterInfo.Category != "OST_MechanicalEquipment")
					{
						string item = element.GetParameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).AsValueString();
						if (!this.m_lstSystem.Contains(item))
						{
							continue;
						}
					}
					FamilyInstance familyInstance = element as FamilyInstance;
					string name = familyInstance.Symbol.Family.Name;
					string name2 = familyInstance.Symbol.Family.Name;
					string strDetailInfo = "";
					this.GetParmInfo(element, filterInfo.ValueType, filterInfo.ConnSymbol, filterInfo.BuiltInParm, ref strDetailInfo);
					ElemParm value = new ElemParm(name, name2, strDetailInfo, filterInfo.Unit, 1.0, "", filterInfo.DetailFilter);
					dicSubItems.Add(element.Id, value);
				}
			}
		}

		private void GetSystemFamilyInfo(FilterInfo filterInfo, FilteredElementCollector collector, BuiltInCategory biCategory, double dCurElevation, ref Dictionary<ElementId, ElemParm> dicSubItems)
		{
			foreach (Element element in collector.OfCategory(biCategory).ToElements())
			{
				if (this.m_bLink || !dicSubItems.ContainsKey(element.Id))
				{
					if (filterInfo.Class == "Pipe")
					{
						Pipe pipe = element as Pipe;
						if (pipe == null)
						{
							continue;
						}
						ElementId elementId = pipe.GetParameter(BuiltInParameter.RBS_PIPE_SEGMENT_PARAM).AsElementId();
						PipeSegment pipeSegment = this.m_doc.GetElement(elementId) as PipeSegment;
						if (!this.m_lstPipeMaterial.Contains(pipeSegment.Name))
						{
							continue;
						}
					}
					if (filterInfo.Category != "OST_MechanicalEquipment")
					{
						string item = element.GetParameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).AsValueString();
						if (!this.m_lstSystem.Contains(item))
						{
							continue;
						}
					}
					string strName = element.GetParameter(BuiltInParameter.ELEM_FAMILY_PARAM).AsValueString() + "_" + element.Name;
					string strDetailInfo = "";
					this.GetParmInfo(element, filterInfo.ValueType, filterInfo.ConnSymbol, filterInfo.BuiltInParm, ref strDetailInfo);
					double dAmount = 0.0;
					this.GetElemAmount(element, filterInfo.Name, biCategory, filterInfo.Amount, filterInfo.Lg, dCurElevation, ref dAmount);
					ElemParm elemParm = new ElemParm("", strName, strDetailInfo, filterInfo.Unit, dAmount, "", filterInfo.DetailFilter);
					this.AddInDictionary(element.Id, elemParm, ref dicSubItems);
				}
			}
		}

		private void GetSystemFamilyInfo(FilterInfo filterInfo, BuiltInCategory biCategory, ref Dictionary<ElementId, ElemParm> dicSubItems)
		{
			foreach (Element element in this.m_lstElemInSelArea)
			{
                if (!dicSubItems.ContainsKey(element.Id) && element.Category.Id.IntegerValue == (int)biCategory)
				{
					if (filterInfo.Class == "Pipe")
					{
						ElementId elementId = (element as Pipe).GetParameter(BuiltInParameter.RBS_PIPE_SEGMENT_PARAM).AsElementId();
						PipeSegment pipeSegment = this.m_doc.GetElement(elementId) as PipeSegment;
						if (!this.m_lstPipeMaterial.Contains(pipeSegment.Name))
						{
							continue;
						}
					}
					if (filterInfo.Category != "OST_MechanicalEquipment")
					{
						string item = element.GetParameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).AsValueString();
						if (!this.m_lstSystem.Contains(item))
						{
							continue;
						}
					}
					string strName = element.GetParameter(BuiltInParameter.ELEM_FAMILY_PARAM).AsValueString() + "_" + element.Name;
					string strDetailInfo = "";
					this.GetParmInfo(element, filterInfo.ValueType, filterInfo.ConnSymbol, filterInfo.BuiltInParm, ref strDetailInfo);
					double dAmount = 0.0;
					this.GetElemAmount(element, filterInfo.Name, biCategory, filterInfo.Amount, filterInfo.Lg, this.m_view.GenLevel.Elevation, ref dAmount);
					ElemParm value = new ElemParm("", strName, strDetailInfo, filterInfo.Unit, dAmount, "", filterInfo.DetailFilter);
					dicSubItems.Add(element.Id, value);
				}
			}
		}

		private void GetElemAmount(Element elem, string elemName, BuiltInCategory bic, uint nAmount, bool bLg, double dCurElevation, ref double value)
		{
			if (nAmount == 0u)
			{
				value = 1.0;
				return;
			}
			if (nAmount == 1u)
			{
				if (!bLg)
				{
					value = elem.GetParameter(BuiltInParameter.CURVE_ELEM_LENGTH).AsDouble();
				}
				else
				{
					LocationCurve locationCurve = elem.Location as LocationCurve;
					XYZ hyendPoint;
					XYZ hyendPoint2;
					if (locationCurve.Curve.GetEndPoint(0).Z - locationCurve.Curve.GetEndPoint(1).Z > 1E-09)
					{
						hyendPoint = locationCurve.Curve.GetEndPoint(1);
						hyendPoint2 = locationCurve.Curve.GetEndPoint(0);
					}
					else
					{
						hyendPoint = locationCurve.Curve.GetEndPoint(0);
						hyendPoint2 = locationCurve.Curve.GetEndPoint(1);
					}
					double num = (hyendPoint - hyendPoint2).AngleTo(XYZ.BasisZ);
					if (num < 0.0001 || Geometry.IsEqual(num, Math.PI))
					{
						double num2 = hyendPoint2.Z;
						for (int i = 0; i < this.m_lstSortLevel.Count; i++)
						{
							if (Math.Abs(this.m_lstSortLevel[i].Elevation - dCurElevation) < 1E-09 && i != 0)
							{
								num2 = this.m_lstSortLevel[i - 1].Elevation;
								break;
							}
						}
						if (Geometry.GreaterThan(hyendPoint2.Z, num2) && Geometry.LessThan(hyendPoint.Z, dCurElevation))
						{
							value = num2 - dCurElevation;
						}
						else if (Geometry.GreaterThan(hyendPoint2.Z, num2) && Geometry.GreaterThan(hyendPoint.Z, dCurElevation))
						{
							value = hyendPoint.Z - dCurElevation;
						}
						else if (Geometry.LessThan(hyendPoint2.Z, num2) && Geometry.LessThan(hyendPoint.Z, dCurElevation))
						{
							value = hyendPoint2.Z - dCurElevation;
						}
						else
						{
							value = elem.GetParameter(BuiltInParameter.CURVE_ELEM_LENGTH).AsDouble();
						}
					}
					else
					{
						value = elem.GetParameter(BuiltInParameter.CURVE_ELEM_LENGTH).AsDouble();
					}
				}
				value = UnitConvert.CovertFromAPI((Autodesk.Revit.DB.DisplayUnitType)0, value);
				return;
			}
			if (nAmount == 2u)
			{
				Pipe elem2 = elem as Pipe;
				string text = elem2.GetParameter(BuiltInParameter.RBS_REFERENCE_INSULATION_TYPE).AsString();
				if (text == null || text == "")
				{
					value = 0.0;
				}
				else
				{
					value = elem2.GetParameter(BuiltInParameter.RBS_CURVE_SURFACE_AREA).AsDouble();
				}
				value = UnitConvert.CovertFromAPI((Autodesk.Revit.DB.DisplayUnitType)12, value);
			}
		}

		private void GetParmInfo(Element elem, uint valueType, string strConnSymbol, string builtInParm, ref string strParm)
		{
			switch (valueType)
			{
			case 1u:
			{
				FamilyInstance familyInstance = elem as FamilyInstance;
				if (this.StringIsNumber(builtInParm) && Convert.ToInt16(builtInParm) == 0)
				{
					strParm += familyInstance.Symbol.Family.Name;
					return;
				}
				try
				{
					BuiltInParameter parameterId = (BuiltInParameter)Enum.Parse(typeof(BuiltInParameter), builtInParm);
					strParm += familyInstance.Symbol.Family.GetParameter(parameterId).ToString();
					return;
				}
				catch
				{
					strParm += familyInstance.Symbol.Family.GetParameter(builtInParm).ToString();
					return;
				}
				break;
			}
			case 2u:
				break;
			case 3u:
				goto IL_22F;
			case 4u:
				strParm = elem.GetParameter(builtInParm).AsString();
				return;
			case 5u:
				strParm = elem.GetParameter(builtInParm).AsString();
				return;
			case 6u:
			{
				string[] array = builtInParm.Split(new char[]
				{
					'#'
				});
				int num = 0;
				foreach (string text in array)
				{
					if (!(text == ""))
					{
						string[] array3 = text.Split(new char[]
						{
							'$'
						});
						uint valueType2 = Convert.ToUInt32(array3[0]);
						this.GetParmInfo(elem, valueType2, strConnSymbol, array3[1], ref strParm);
						if (num != array.Count<string>() - 1 && strParm != "")
						{
							strParm += strConnSymbol;
						}
						num++;
					}
				}
				return;
			}
			default:
				return;
			}
			FamilyInstance familyInstance2 = elem as FamilyInstance;
			if (this.StringIsNumber(builtInParm) && Convert.ToInt16(builtInParm) == 0)
			{
				strParm += familyInstance2.Symbol.Name;
				return;
			}
			try
			{
				BuiltInParameter parameterId2 = (BuiltInParameter)Enum.Parse(typeof(BuiltInParameter), builtInParm);
				strParm += familyInstance2.Symbol.GetParameter(parameterId2).ToString();
				return;
			}
			catch
			{
				if (builtInParm == "扬程")
				{
					double value = familyInstance2.Symbol.GetParameter(builtInParm).AsDouble();
					string str = UnitConvert.CovertFromAPI(0, value).ToString("0.00");
					this.RemoveInvalidDecimal(ref str);
					strParm = strParm + str + " m";
				}
				else if (builtInParm == "流量")
				{
					double value2 = familyInstance2.Symbol.GetParameter(builtInParm).AsDouble();
					value2 = UnitConvert.CovertFromAPI((Autodesk.Revit.DB.DisplayUnitType)64, value2);
					string text2 = value2.ToString("0.00");
					this.RemoveInvalidDecimal(ref text2);
					strParm = strParm + value2.ToString("0.00") + " L/s";
				}
				else
				{
					double dLength = familyInstance2.Symbol.GetParameter(builtInParm).AsDouble();
					string str2 = UnitConvert.LengthConverFromAPI(this.m_doc, dLength).ToString("0.00");
					this.RemoveInvalidDecimal(ref str2);
					strParm += str2;
				}
				return;
			}
			IL_22F:
			BuiltInParameter parameterId3 = (BuiltInParameter)Enum.Parse(typeof(BuiltInParameter), builtInParm);
			strParm += this.GetParameterValue(elem.GetParameter(parameterId3));
		}

		private void RemoveInvalidDecimal(ref string strValue)
		{
			if (strValue.IndexOf('.') != -1)
			{
				strValue = strValue.TrimEnd(new char[]
				{
					'0'
				});
				strValue = strValue.Trim(new char[]
				{
					'.'
				});
			}
		}

		private bool StringIsNumber(string strValue)
		{
			return Regex.IsMatch(strValue, "^\\d+$") || Regex.IsMatch(strValue, "^\\d+\\.\\d+$");
		}

		private void FilterSystem(ref IList<Element> lstElem)
		{
			foreach (Element element in lstElem)
			{
				string item = element.GetParameter(BuiltInParameter.RBS_DUCT_SYSTEM_TYPE_PARAM).AsValueString();
				if (!this.m_lstSystem.Contains(item))
				{
					lstElem.Remove(element);
				}
			}
		}

		private void ElementInLinkDoc()
		{
			if (this.m_view3D == null)
			{
				return;
			}
			List<RevitLinkInstance> allRevitLinkInstancesInDoc = this.GetAllRevitLinkInstancesInDoc();
			if (allRevitLinkInstancesInDoc.Count <= 0)
			{
				return;
			}
			ProgressBarForm progressBarForm = new ProgressBarForm(this.m_lstFilterInfo.Count * (this.m_lstLevelValue.Count - 1), "正在统计链接文档中的数据", ProgressBarStyle.Blocks, true, false, false);
			progressBarForm.Show(WindowHelper.HWndRevit);
			for (int i = 0; i < this.m_lstFilterInfo.Count; i++)
			{
				Dictionary<ElementId, ElemParm> item = new Dictionary<ElementId, ElemParm>();
				for (int j = 0; j < this.m_lstLevelValue.Count - 1; j++)
				{
					progressBarForm.RefreshProgressBar();
					if (progressBarForm.m_stopTag)
					{
						return;
					}
					double num = this.m_lstLevelValue[j];
					double val = this.m_lstLevelValue[j + 1];
					foreach (RevitLinkInstance revitLinkInstance in allRevitLinkInstancesInDoc)
					{
						Document linkDocument = revitLinkInstance.GetLinkDocument();
						if (linkDocument != null)
						{
							BoundingBoxXYZ boundingBoxXYZ = revitLinkInstance.get_BoundingBox(this.m_view3D);
							if (boundingBoxXYZ != null)
							{
								double z = boundingBoxXYZ.Min.Z;
								if (!Geometry.LessThan(z, num) && !Geometry.GreaterThan(z, val))
								{
									try
									{
										FilteredElementCollector collector = new FilteredElementCollector(linkDocument);
										BuiltInCategory biCategory = (BuiltInCategory)Enum.Parse(typeof(BuiltInCategory), this.m_lstFilterInfo[i].Category);
										if (this.m_lstFilterInfo[i].Class == "FamilyInstance")
										{
											this.GetNonSystemFamilyInfo(this.m_lstFilterInfo[i], collector, biCategory, ref item);
										}
										else
										{
											this.GetSystemFamilyInfo(this.m_lstFilterInfo[i], collector, biCategory, num, ref item);
										}
									}
									catch
									{
									}
								}
							}
						}
					}
				}
				this.m_lstDicElement.Add(item);
			}
		}

		private List<RevitLinkInstance> GetAllRevitLinkInstancesInDoc()
		{
			IEnumerable<ElementId> enumerable = new FilteredElementCollector(this.m_doc).OfClass(typeof(RevitLinkInstance)).ToElementIds();
			List<RevitLinkInstance> list = new List<RevitLinkInstance>();
			foreach (ElementId elementId in enumerable)
			{
				Element element = this.m_doc.GetElement(elementId);
				if (!(element.GetType() != typeof(RevitLinkInstance)))
				{
					RevitLinkInstance revitLinkInstance = element as RevitLinkInstance;
					if (revitLinkInstance != null)
					{
						list.Add(revitLinkInstance);
					}
				}
			}
			return list;
		}

		private List<double> GetLevelValue()
		{
			List<double> list = new List<double>();
			foreach (ViewPlan viewPlan in this.m_lstViewPlan)
			{
				if (!list.Contains(viewPlan.GenLevel.Elevation))
				{
					list.Add(viewPlan.GenLevel.Elevation);
				}
			}
			list.Sort();
			return list;
		}

		private View3D GetView3D()
		{
			List<Element> list = new FilteredElementCollector(this.m_doc).OfClass(typeof(View3D)).OfCategory(BuiltInCategory.OST_Views).ToElements().ToList<Element>();
			View3D view3D = null;
			if (list.Count > 0)
			{
				foreach (Element element in list)
				{
					view3D = (element as View3D);
					if (RevitVersionFuncs.GetViewName(view3D) == "三维统计")
					{
						return view3D;
					}
				}
			}
			Transaction transaction = new Transaction(this.m_doc, "Create 3D view");
			transaction.Start();
			try
			{
				XYZ direction = new XYZ(-1.0, 1.0, -1.0);
				view3D = RevitVersionFuncs.NewView3D(this.m_doc, direction);
				Autodesk.Revit.DB.View view = view3D;
				RevitVersionFuncs.SetViewName(ref view, "三维统计");
				view3D = (view as View3D);
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
			}
			return view3D;
		}

		private void AddInDictionary(ElementId idElem, ElemParm elemParm, ref Dictionary<ElementId, ElemParm> dicElement)
		{
			if (!this.m_bLink)
			{
				dicElement.Add(idElem, elemParm);
				return;
			}
			if (dicElement.ContainsKey(idElem))
			{
				dicElement[idElem].Amount += elemParm.Amount;
				return;
			}
			dicElement.Add(idElem, elemParm);
		}

		private string GetParameterValue(Parameter parm)
		{
			string result = "";
			if (parm == null)
			{
				return result;
			}
            switch ((int)parm.StorageType)
			{
			case 1:
				result = parm.AsInteger().ToString();
				break;
			case 2:
				result = parm.AsValueString();
				break;
			case 3:
				result = parm.AsString();
				break;
			case 4:
				result = parm.AsElementId().ToString();
				break;
			}
			return result;
		}

		public List<Dictionary<ElementId, ElemParm>> m_lstDicElement = new List<Dictionary<ElementId, ElemParm>>();

		private Document m_doc;

		private List<ViewPlan> m_lstViewPlan;

		private bool m_bLink;

		private List<FilterInfo> m_lstFilterInfo;

		private List<string> m_lstSystem = new List<string>();

		private List<string> m_lstPipeMaterial = new List<string>();

		private List<Level> m_lstSortLevel;

		private ViewPlan m_view;

		private List<Element> m_lstElemInSelArea;

		private List<double> m_lstLevelValue;

		private View3D m_view3D;

		private const double _epsDouble = 1E-09;
	}
}
